#include "player.h"
#include <cstring>

Player::Player()
{
    memset(&keyState,0,sizeof(keyState));
    memset(&moveState,0,sizeof(moveState));
    memset(&attrState,0,sizeof(attrState));
    moveState.stand_static = 1;
    directState = DirectState::RIGHT;

    attrState.hasWeapon = 1;
    attrState.growup = 1;

    initControlConfig();
    listenKeyboardEvent();

    move.x = move.y = 0;
    hspeed = 200;
    vspeed = 80;
    hmaxspeed = 200;
    vmaxspeed =80;
    hacceleration = 300;
    vacceleration = 400;
    moveState.jump = 1;

    moveRange.bottom = 100;
    moveRange.left = 100;
    moveRange.right = 100;
    moveRange.top = 100;

    std::cout << "ABCD\n";
}

Player::~Player()
{
}

void Player::initControlConfig(void)
{
    keyMap["JUMP"] = EventKeyboard::KeyCode::KEY_SPACE;
    keyMap["LEFT"] = EventKeyboard::KeyCode::KEY_A;
    keyMap["RIGHT"] = EventKeyboard::KeyCode::KEY_D;
    keyMap["SQUAT"] = EventKeyboard::KeyCode::KEY_S;
    keyMap["FIRE"] = EventKeyboard::KeyCode::KEY_M;
}

bool Player::loadResources(const string& spritexfile,const string&fn)
{
    SpriteX spx(spritexfile);

    if( spx.actionCount != 25 ){
        return false;
    }

    Texture2D* texture = Director::getInstance()->getTextureCache()->addImage(fn);
    if( !texture ){
        return false;
    }


    for( int i = 0 ; i < 25 ; i ++ ){
        Animation* animation = SpriteXAnimation::create(texture,&spx,i);
        animation->setLoops(-1);
        animation->setDelayPerUnit(0.05f);
        action[i] = Animate::create(animation);
        action[i]->retain();
    }

    actionState.curraction = (int)ActionType::NONE;
    actionState.newaction = (int)ActionType::STATIC_SMALL;

    return true;
}

void Player::actionChange(void)
{
    if( actionState.curraction != actionState.newaction ){
        stopAllActions();
        runAction(action[(int)actionState.newaction]);
        actionState.curraction = actionState.newaction;
    }
}

void Player::handleKeyPressedEvent(EventKeyboard::KeyCode keycode, Event* e)
{
    if( keyMap["JUMP"] == keycode ){
        keyState.jump = 1;
    }else if( keyMap["SQUAT"] == keycode ){
        keyState.squat = 1;
    }else if( keyMap["FIRE"] == keycode ){
        keyState.fire = 1;
    }else if( keyMap["LEFT"] == keycode && keyState.left == 0 ){
        // key.left is pressed at first time
        if( keyState.right == 1 ){
            //if the key.right is still pressed , set key.left to 2 ,
            //this means that current valid key is key.left
            keyState.left = 2;
        }else{
            //if the key.right is not pressed , just set key.left to 1 ,
            //this also means that current valid key is key.left
            keyState.left = 1;
        }
        if( moveState.jump == 0 )
            moveState.walk = 1;
    }else if( keyMap["RIGHT"] == keycode && keyState.right == 0 ){
        // key.right is pressed at first time
        if( keyState.left == 1 ){
            //if the key.left is still pressed , set key.right to 2 ,
            //this means that current valid key is key.right
            keyState.right = 2;
        }else{
            //if key.left is not pressed , just set key.right to 1
            //this also means that current valid is key.right
            keyState.right = 1;
        }
        if( moveState.jump == 0 )
            moveState.walk = 1;
    }
}

void Player::handleKeyReleasedEvent(EventKeyboard::KeyCode keycode, Event* e)
{
    if( keyMap["RIGHT"] == keycode  ){
        //if key.right is released , check key.left
        //if key.left == 2 , this means key.left and
        //key.right were both pressed , now key.right
        //is released , we set key.left to 1 , means that
        // only key.right is pressed now
        keyState.right = 0;
        if( keyState.left == 2 )
            keyState.left = 1;
    }else if( keyMap["LEFT"] == keycode ){
        keyState.left = 0;
        if( keyState.right == 2 )
            keyState.right = 1;
    }else if( keyMap["SQUAT"] == keycode ){
        keyState.squat = 0;
    }else if( keyMap["FIRE"] == keycode ){
        keyState.fire = 0;
    }else if( keyMap["JUMP"] == keycode ){
        keyState.jump = 0;
    }
}

void Player::listenKeyboardEvent(void)
{
    EventListenerKeyboard* keyboardListener = EventListenerKeyboard::create();

    keyboardListener->onKeyPressed = [this](EventKeyboard::KeyCode keycode, Event* e){
        this->handleKeyPressedEvent(keycode,e);
    };

    keyboardListener->onKeyReleased = [this](EventKeyboard::KeyCode keycode, Event* e){
        this->handleKeyReleasedEvent(keycode,e);
    };

    _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener,this);
}

void Player::updatePosition(float delta)
{
    //jump state update
    if( keyState.left > keyState.right ){
        if( hspeed > -hmaxspeed ){
            hspeed -= hacceleration*delta;
            if( hspeed < -hmaxspeed )
                hspeed = -hmaxspeed;
        }
    }else if( keyState.right > keyState.left ){
        if( hspeed < hmaxspeed ){
            hspeed += hacceleration*delta;
            if( hspeed > hmaxspeed )
                hspeed = hmaxspeed;
        }
    }else if( hspeed > 0 ){
        hspeed -= hacceleration*delta;
        if( hspeed < 0 )
            hspeed = 0;
    }else if( hspeed < 0 ){
        hspeed += hacceleration*delta;
        if( hspeed > 0 )
            hspeed = 0;
    }
    move.x = hspeed*delta;

    vspeed -= vacceleration*delta;
    move.y = vspeed*delta;

    //adjust position
    if( move.x > 0 ){
        if( moveRange.right < move.x ){
            move.x = moveRange.right;
        }
    }else if( move.x < 0 ){
        if( -moveRange.left > move.x ){
            move.x = -moveRange.left;
        }
    }
    if( move.y > 0 ){
        if( moveRange.top < move.y ){
            move.y = moveRange.top;
        }
    }else if( move.y < 0 ){
        if( -moveRange.bottom > move.y ){
            move.y = -moveRange.bottom;
        }
    }
}

void Player::checkMoveRange(void *levelMap,list<Sprite *> &objList)
{

}

void Player::adjustPosition(void)
{

}

void Player::doMove(void)
{
    setPosition(move+getPosition());
    setFlippedX((moveState.facetoleft==0)?false:true);
}

void Player::updateMoveState(void)
{
    if( moveRange.bottom == 0.0 ){
        vspeed = 0.0;
        moveState.jump = 0.0;
    }
    if( moveState.jump == 0 ){
        if( keyState.jump == 1 ){
            vspeed = vmaxspeed;
            moveState.jump = 1;
        }
    }

    //squat state update
    if( keyState.squat ){
        moveState.squat = 1;
    }else{
        moveState.squat = 0;
    }

    if( keyState.left > keyState.right){
        if( hspeed > 0 && moveState.jump == 0 ){
            moveState.faststop = 1;
        }else{
            moveState.faststop = 0;
        }
    }else if( keyState.right > keyState.left ){
        if( hspeed < 0 && moveState.jump == 0 ){
            moveState.faststop = 1;
        }else{
            moveState.faststop = 0;
        }
    }else if( hspeed == 0.0 ){
        moveState.walk = 0;
        moveState.faststop = 0;
    }
    if( hspeed > 0 ){
        moveState.facetoleft = 0;
        moveState.walk = 1;
    }else if( hspeed < 0 ){
        moveState.facetoleft = 1;
        moveState.walk = 1;
    }

    if( keyState.fire ){
        moveState.attack = 1;
        ;//current action
    }else{
        moveState.attack = 0;
    }
}

void Player::updateActionState(void)
{
    if( moveState.squat ){
        if( attrState.hasWeapon ){
            actionState.newaction = (int)ActionType::SQUAT_BIG_W;
        }else if( attrState.growup ){
            actionState.newaction = (int)ActionType::SQUAT_BIG;
        }
    }else if( moveState.jump ){
        if( attrState.hasWeapon ){
            actionState.newaction = (int)ActionType::JUMP_BIG_W;
        }else if( attrState.growup ){
            actionState.newaction = (int)ActionType::JUMP_BIG;
        }else{
            actionState.newaction = (int)ActionType::JUMP_SMALL;
        }
    }else if( moveState.faststop ){
        if( attrState.hasWeapon ){
            actionState.newaction = (int)ActionType::FASTSTOP_BIG_W;
        }else if( attrState.growup ){
            actionState.newaction = (int)ActionType::FASTSTOP_BIG;
        }else{
            actionState.newaction = (int)ActionType::FASTSTOP_SMALL;
        }
    }else if( moveState.walk ){
        if( attrState.hasWeapon ){
            actionState.newaction = (int)ActionType::WALK_BIG_W;
        }else if( attrState.growup ){
            actionState.newaction = (int)ActionType::WALK_BIG;
        }else{
            actionState.newaction = (int)ActionType::WALK_SMALL;
        }
    }else{
        if( attrState.hasWeapon ){
            actionState.newaction = (int)ActionType::STATIC_BIG_W;
        }else if( attrState.growup ){
            actionState.newaction = (int)ActionType::STATIC_BIG;
        }else{
            actionState.newaction = (int)ActionType::STATIC_SMALL;
        }
    }
}

void Player::doAction(void)
{
    actionChange();
}

void Player::update(float delta)
{
    updatePosition(delta);
    doMove();
    updateMoveState();
    updateActionState();
    doAction();

    std::cout << "x : " << getPositionX() << " y : " << getPositionY() << std::endl;
    std::cout << "Left : " << keyState.left << " Right : " << keyState.right << std::endl;
    if( keyState.left > keyState.right ){
        std::cout << "Left\n";
    }else if( keyState.left < keyState.right ){
        std::cout << "Right\n";
    }else{
        std::cout << "No Key Down\n";
    }
    std::cout << "V Speed : " << vspeed << std::endl;
}

Player::ActionType Player::choiceAction(void)
{
    return ActionType::NONE;
}
